/*
* 在面向对象软件的过程中针对特定的问题简洁而优雅的解决方案
* 模式分类
* 1.创建型 工厂 单例 原型
* 2.组合型 适配器 装饰器 代理 外观 桥接
* 3.行为型 观察者 命令 中介者 状态 策略 迭代器 访问者 模板方法 职责链 备忘录
**/
//1.工厂模式 将new 操作单独封装 只对外提供相应接口 遇到new时，就要考虑是否使用工厂模式
class Product{
    constructo(name){
        this.name=name;
    }
    init(){
        console.log('初始化产品');
    }
}
class Factory {
    create(name){
        return new Product(name);
    }
}
let c=new Factory();
let p=c.create('p1');
p.init();
class User {
    constructor(name = '', viewPage = []) {
        this.name = name;
        this.viewPage = viewPage;
    }
}

class UserFactory extends User {
    constructor(name, viewPage) {
        super(name, viewPage)
    }
    create(role) {
        switch (role) {
            case 'superAdmin':
                return new UserFactory( '超级管理员', ['首页', '通讯录', '发现页', '应用数据', '权限管理'] );
                break;
            case 'admin':
                return new UserFactory( '管理员', ['首页', '通讯录'] );
                break;
            default:
                throw new Error('params error');
        }
    }
}
let userFactory = new UserFactory();
let superAdmin = userFactory.create('superAdmin');
let admin = userFactory.create('admin');
// let user = userFactory.create('user');
//=============实战重的应用场景 jQuery的选择器$(selector) Vue异步组件 React.createElement()
//1.单例模式 保证实例在全局的单一性 系统中被唯一调用 一个类只有一个实例 必须是=== 创建一个可以返回对象实例的引用和获取该实例的方法 保证创建对象的引用恒唯一
class Modal {
    login() {
        console.log('login...');
    }
}
Modal.create = (function() {
    let instance
    return function() {
        if(!instance) {
            instance = new Modal();
        }
        return instance
    }
})()
let m1 = Modal.create();
let m2 = Modal.create();
console.log(m1 === m2) // true

let Modal2 = (function(){
    let instance;
    return function(name) {
        if (instance) {
            return instance;
        }
        this.name = name;
        return instance = this;
    }
})();

Modal2.prototype.getName = function() {
    return this.name
}

let question = new Modal2('问题框');
let answer = new Modal2('回答框');
console.log(question === answer); // true
console.log(question.getName());  // '问题框'
console.log(answer.getName());  // '问题框'
//==============应用场景 vuex react中的store
//-----------------------------------------观察者模式
//创建一个主题 保存状态 状态变化之后 触发所有的观察者对象
class Subject {
    constructor(){
        this.state=0;
        this.observers=[];
    }
    getState() {
        return this.state
    }

    setState(state) {
        this.state = state;
        this.notifyAllObservers()
    }

    notifyAllObservers() {
        this.observers.forEach(observer => {
            observer.update()
        })
    }

    attach(observer) {
        this.observers.push(observer)
    }

}
// 观察者
class Observer {
    constructor(name , subject) {
        this.name = name;
        this.subject = subject;
        this.subject.attach(this);
    }
    update() {
        console.log(`${this.name} update, state: ${this.subject.getState()}`)
    }
}
let s = new Subject();
let o1 = new Observer('o1' , s);
let o2 = new Observer('o2' , s);
let o3 = new Observer('o3' , s);
s.setState(1)